home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / grafica / pvrgjpeg / jpeg.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  62KB  |  2,210 lines

  1. /*************************************************************
  2. Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
  3. PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
  4. Group. If you use this software, you agree to the following: This
  5. program package is purely experimental, and is licensed "as is".
  6. Permission is granted to use, modify, and distribute this program
  7. without charge for any purpose, provided this license/ disclaimer
  8. notice appears in the copies.  No warranty or maintenance is given,
  9. either expressed or implied.  In no event shall the author(s) be
  10. liable to you or a third party for any special, incidental,
  11. consequential, or other damages, arising out of the use or inability
  12. to use the program for any purpose (or the loss of data), even if we
  13. have been advised of such possibilities.  Any public reference or
  14. advertisement of this source code should refer to it as the Portable
  15. Video Research Group (PVRG) code, and not by any author(s) (or
  16. Stanford University) name.
  17. *************************************************************/
  18. /*
  19. ************************************************************
  20. jpeg.c
  21.  
  22. This file contains the main calling routines for the JPEG coder.
  23.  
  24. ************************************************************
  25. */
  26.  
  27. /*LABEL jpeg.c */
  28.  
  29. /* Include files. */
  30.  
  31. #include "tables.h"
  32. #include "globals.h"
  33. #ifdef SYSV
  34. #include <sys/fcntl.h>
  35. #endif
  36.  
  37. /*
  38.   Define the functions to be used with ANSI prototyping.
  39.   */
  40.  
  41. /*PUBLIC*/
  42.  
  43. int main();
  44. static void JpegEncodeFrame();
  45. static void JpegDecodeFrame();
  46. static void JpegDecodeScan();
  47. static void JpegLosslessDecodeScan();
  48. static void Help();
  49.  
  50. extern void PrintImage();
  51. extern void PrintFrame();
  52. extern void PrintScan();
  53. extern void MakeImage();
  54. extern void MakeFrame();
  55. extern void MakeScanFrequency();
  56. extern void MakeScan();
  57. extern void MakeConsistentFileNames();
  58. extern void CheckValidity();
  59. extern int CheckBaseline();
  60. extern void ConfirmFileSize();
  61. extern void JpegQuantizationFrame();
  62. extern void JpegDefaultHuffmanScan();
  63. extern void JpegFrequencyScan();
  64. extern void JpegCustomScan();
  65. extern void JpegEncodeScan();
  66.  
  67. extern void JpegLosslessFrequencyScan();
  68. extern void JpegLosslessEncodeScan();
  69.  
  70. /*PRIVATE*/
  71.  
  72. /* These variables occur in the stream definition. */
  73.  
  74. extern int CleartoResync;  
  75. extern int LastKnownResync;
  76. extern int ResyncEnable;   
  77. extern int ResyncCount;    
  78. extern int EndofFile;      
  79. extern int EndofImage;     
  80.  
  81. /* Define the parameter passing structures. */
  82. IMAGE *CImage=NULL;           /* Current Image variables structure */
  83. FRAME *CFrame=NULL;           /* Current Frame variables structure */
  84. SCAN *CScan=NULL;             /* Current Scan variables structure */
  85.  
  86. /* Define the MDU counters. */
  87. int CurrentMDU=0;             /* Holds the value of the current MDU */
  88. int NumberMDU=0;              /* This number is the number of MDU's */
  89.  
  90. /* Define Lossless info */
  91.  
  92. int LosslessPredictorType=0;  /* The lossless predictor used */
  93. int PointTransform=0;         /* This parameter affects the shifting in io.c */
  94.  
  95. /* How we break things up */
  96.  
  97. int ScanComponentThreshold=SCAN_COMPONENT_THRESHOLD;
  98.  
  99. /* Define the support/utility variables.*/
  100. int ErrorValue=0;             /* Holds error upon return */
  101. int Loud=MUTE;                /* Loudness gives level of debug traces */
  102. int HuffmanTrace=NULL;        /* When set, dumps Huffman statistics */
  103. int Notify=1;                 /* When set, gives image size feedback */
  104. int Robust=0;
  105. static int LargeQ=0;          /* When set, large quantization is enabled */
  106.  
  107. /* We default to the Chen DCT algorithm. */
  108. vFunc *UseDct = ChenDct;       /* This is the DCT algorithm to use */
  109. vFunc *UseIDct = ChenIDct;     /* This is the inverse DCT algorithm to use */
  110.  
  111. /* Add some macros to ease readability. */
  112. #define DefaultDct (*UseDct)    
  113. #define DefaultIDct (*UseIDct)
  114.  
  115. /*START*/
  116.  
  117. /*BFUNC
  118.  
  119. main() is first called by the shell routine upon execution of the
  120. program.
  121.  
  122. EFUNC*/
  123.  
  124. int main(argc,argv)
  125.      int argc;
  126.      char **argv;
  127. {
  128.   BEGIN("main");
  129.   int i,ComponentIndex;
  130.   int Oracle=0;     /* Oracle means that we use the lexer interactively */
  131.  
  132.   MakeImage();      /* Construct the image structures */
  133.   MakeFrame();
  134.   MakeScan();
  135.  
  136.   if (argc == 1)    /* No arguments then print help info */
  137.     {
  138.       Help();
  139.       exit(-1);
  140.     }
  141.  
  142.   ComponentIndex=1;  /* Start with index 1 (Could be zero, but JFIF compat) */
  143.   for(i=1;i<argc;i++)  /* Else loop through all arguments. */
  144.     {
  145.       if (!strcmp(argv[i],"-JFIF"))
  146.     CImage->Jfif=1;
  147.       else if (!strcmp(argv[i],"-ci"))
  148.     ComponentIndex=atoi(argv[++i]);
  149.       else if (*(argv[i]) == '-')       /* Strip off first "dash" */
  150.      {
  151.        switch(*(++argv[i]))
  152.          {
  153.         case 'a':                      /* -a Reference DCT */
  154.           UseDct = ReferenceDct;
  155.           UseIDct = ReferenceIDct;
  156.           break;
  157.         case 'b':                      /* -b Lee DCT */
  158.           UseDct = LeeDct;
  159.           UseIDct = LeeIDct;
  160.           break;
  161.          case 'd':                      /* -d Decode */
  162.           CImage->JpegMode = J_DECODER;
  163.            break; 
  164.          case 'k':                      /* -k Lossless mode */
  165.           CImage->JpegMode = J_LOSSLESS;
  166.           CFrame->Type=3;
  167.           LosslessPredictorType = atoi(argv[++i]);
  168.            break; 
  169.         case 'f':
  170.            switch(*(++argv[i]))
  171.          {
  172.          case 'w':                 /* -fw Frame width */
  173.            CFrame->Width[ComponentIndex] =
  174.             atoi(argv[++i]);
  175.           break;
  176.         case 'h':                 /* -fh Frame height */
  177.           CFrame->Height[ComponentIndex] =
  178.             atoi(argv[++i]);
  179.           break;
  180.         default:
  181.           WHEREAMI();
  182.           printf("Illegal option: f%c.\n",
  183.              *argv[i]);
  184.           exit(ERROR_BOUNDS);
  185.           break;
  186.         }
  187.           break;
  188.         case 'i':    
  189.           switch(*(++argv[i]))
  190.         {
  191.         case 'w':                /* -iw Image width */
  192.           CFrame->GlobalWidth = atoi(argv[++i]);
  193.           break;
  194.         case 'h':                /* -ih Image height */
  195.           CFrame->GlobalHeight = atoi(argv[++i]);
  196.           break;
  197.         default:
  198.           WHEREAMI();
  199.           printf("Illegal option: i%c.\n",
  200.              *argv[i]);
  201.           exit(ERROR_BOUNDS);
  202.           break;
  203.         }
  204.           break;
  205.         case 'h':                    /* -h horizontal frequency */
  206.           CFrame->hf[ComponentIndex] =
  207.         atoi(argv[++i]);
  208.           break;
  209. #ifndef PRODUCTION_VERSION
  210.         case 'l':                    /* -l loudness for debugging */
  211.           Loud = atoi(argv[++i]);
  212.           break;
  213. #endif
  214.         case 'n':                    /* Set non-interleaved mode */
  215.           ScanComponentThreshold=1;
  216.           break;
  217.         case 'o':                    /* -o Oracle mode (input parsing)*/
  218.           Oracle=1;
  219.           break;
  220.         case 'p':
  221.           CFrame->DataPrecision = atoi(argv[++i]);
  222.           if (!CFrame->Type) CFrame->Type = 1;
  223.           break;
  224.         case 'r':                    /* -r resynchronization */
  225.           CFrame->ResyncInterval = atoi(argv[++i]);
  226.           break;
  227.         case 'q':                    /* -q Q factor */
  228.           if (*(++argv[i])=='l') LargeQ=1;
  229.           CFrame->Q = atoi(argv[++i]);
  230.           break;
  231.         case 'v':                    /* -v vertical frequency */
  232.           CFrame->vf[ComponentIndex] = atoi(argv[++i]);
  233.           break;
  234.         case 's':                    /* -s stream file name */
  235.           CImage->StreamFileName = argv[++i];
  236.           break;
  237.         case 't':
  238.           PointTransform=atoi(argv[++i]);
  239.           break;
  240. #ifndef PRODUCTION_VERSION
  241.         case 'x':                    /* -x trace */
  242.           HuffmanTrace = 1;
  243.           break;
  244. #endif
  245.         case 'u':                    /* -u disable width/size output */
  246.           Notify=0;
  247.           break;
  248.         case 'y':
  249.           Robust=1;
  250.           break;
  251.         case 'z':                    /* -z use default Huffman */
  252.           CImage->JpegMode |= J_DEFAULTHUFFMAN;
  253.           break;
  254.         default:
  255.           WHEREAMI();
  256.           printf("Illegal option in command line: %c.\n",
  257.              *argv[i]);
  258.           exit(ERROR_BOUNDS);
  259.           break;
  260.         }
  261.     }
  262.       else                               /* If not a "-" then a filename */
  263.     {
  264.       CFrame->cn[CFrame->GlobalNumberComponents++]= ComponentIndex;
  265.       if (!CFrame->vf[ComponentIndex])
  266.         CFrame->vf[ComponentIndex]=1;
  267.       if (!CFrame->hf[ComponentIndex])
  268.         CFrame->hf[ComponentIndex]=1;
  269.       CFrame->ComponentFileName[ComponentIndex] = argv[i];
  270.       ComponentIndex++;
  271.     }
  272.     }
  273.  
  274.   if (Oracle)            /* If Oracle set */
  275.     {
  276.       initparser();      /* Initialize interactive parser */
  277.       parser();          /* parse input from stdin */
  278.       exit(ErrorValue);
  279.     }
  280.  
  281.   /* Otherwise act on information */
  282.  
  283.   if (!(GetFlag(CImage->JpegMode,J_DECODER)) &&  /* Check for files */
  284.       (CFrame->GlobalNumberComponents == 0))
  285.     {
  286.       WHEREAMI();
  287.       printf("No component file specified.\n");
  288.       exit(ERROR_BOUNDS);
  289.     }
  290.   if (CImage->StreamFileName == NULL)            /* Check for stream name */
  291.     {
  292.       if (CFrame->ComponentFileName[CFrame->cn[0]])  /* If doesn't exist */
  293.     {                                            /* Create one. */
  294.       CImage->StreamFileName =
  295.         (char *) calloc(strlen(CFrame->ComponentFileName[CFrame->cn[0]])+6,
  296.                 sizeof(char));
  297.       sprintf(CImage->StreamFileName,"%s.jpg",
  298.           CFrame->ComponentFileName[CFrame->cn[0]]);
  299.     }
  300.       else
  301.     {
  302.       WHEREAMI();
  303.       printf("No stream filename.\n");
  304.       exit(ERROR_BOUNDS);
  305.     }
  306.     }
  307.   if (GetFlag(CImage->JpegMode,J_DECODER))       /* If decoder flag set then */
  308.     {                                            /* decode frame. */
  309.       JpegDecodeFrame();
  310.     }
  311.   else
  312.     {
  313.       if (!(CFrame->GlobalWidth) || !(CFrame->GlobalHeight)) /* Dimensions ? */
  314.     {
  315.       WHEREAMI();
  316.       printf("Unspecified frame size.\n");
  317.       exit(ERROR_BOUNDS);
  318.     }
  319.       swopen(CImage->StreamFileName,0);          /* Open output file, index 0*/
  320.       JpegEncodeFrame();                         /* Encode the frame */
  321.       swclose();                                 /* Flush remaining bits */
  322.     }
  323.   exit(ErrorValue);
  324. }
  325.  
  326. /*BFUNC
  327.  
  328. JpegEncodeFrame() handles the basic encoding of the routines provided that
  329. CFrame and CImage are set up properly. It creates the appropriate
  330. CScan to handle the intermediate variables.
  331.  
  332. EFUNC*/
  333.  
  334. static void JpegEncodeFrame()
  335. {
  336.   BEGIN("JpegEncodeFrame");
  337.   int i,CurrentComponent;
  338.  
  339.   CurrentComponent=0;           /* Write start of image, start of frame */
  340.   WriteSoi();
  341.   if (CImage->Jfif) WriteJfif(); /* Write JFIF marker if necessary */
  342.   MakeConsistentFrameSize();     /* Do it here when everything defined */
  343.   JpegQuantizationFrame();       /* Set up quantization matrices */
  344.   WriteSof();
  345.   if (CFrame->ResyncInterval)   /* If resync enabled put DRI marker */
  346.     {
  347.       WriteDri();
  348.     }
  349.   while(1)                      /* This loop breaks up a large number of */
  350.     {                           /* components into small scans */
  351.       if (CFrame->GlobalNumberComponents<=CurrentComponent)
  352.     {
  353.       break;                /* All encoded */
  354.     }
  355.       else if (CFrame->GlobalNumberComponents-CurrentComponent <=
  356.            ScanComponentThreshold)
  357.     {                       /* If less/equal to (SCT) components do it */
  358.       CScan->NumberComponents =  
  359.         CFrame->GlobalNumberComponents-CurrentComponent;
  360.       for(i=0;CurrentComponent<CFrame->GlobalNumberComponents;
  361.           CurrentComponent++,i++)
  362.         {
  363.           CScan->ci[i]=CFrame->cn[CurrentComponent];
  364.         }
  365.     }
  366.       else
  367.     {                       /* Break into (SCT) componets */
  368.       CScan->NumberComponents = ScanComponentThreshold; 
  369.       for(i=0;i<ScanComponentThreshold;CurrentComponent++,i++)
  370.         {
  371.           CScan->ci[i]=CFrame->cn[CurrentComponent];
  372.         }
  373.     }
  374.       CheckValidity();                  /* Check validity */
  375.       CheckBaseline();                  /* See if type is correct */
  376.  
  377.       if (Loud > MUTE)
  378.     {
  379.       PrintImage();
  380.       PrintFrame();
  381.       PrintScan();
  382.     }
  383.       ConfirmFileSize();                /* Does files on disk agree? */
  384.       if (GetFlag(CImage->JpegMode,J_LOSSLESS))
  385.     {
  386.       MakeIob(IOB_LINE,O_RDONLY,
  387.           ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct*/
  388.       JpegLosslessFrequencyScan();        /* Else make custom stables */
  389.       JpegCustomScan(CUSTOM_DO_DC);
  390.       WriteDht();                         /* write Huffman tables */
  391.       JpegLosslessEncodeScan();
  392.     }
  393.       else if (GetFlag(CImage->JpegMode,J_DEFAULTHUFFMAN))
  394.     {
  395.       MakeIob(IOB_BLOCK,O_RDONLY,
  396.           ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct */
  397.  
  398.       JpegDefaultHuffmanScan();     /* If default tables, then set up */
  399.       WriteDqt();                       /* Write out quantization */
  400.       WriteDht();                       /* and Huffman tables */
  401.       JpegEncodeScan();                 /* Encode the scan */
  402.     }
  403.       else
  404.     {
  405.       MakeIob(IOB_BLOCK,O_RDONLY,
  406.           ((CFrame->DataPrecision>8)?2:1));  /* Make IO read struct*/
  407.       JpegFrequencyScan();              /* Else make custom tables */
  408.       JpegCustomScan(CUSTOM_DO_AC|CUSTOM_DO_DC);
  409.       WriteDqt();                       /* Write out quantization */
  410.       WriteDht();                       /* and Huffman tables */
  411.       JpegEncodeScan();                 /* Encode the scan */
  412.     }
  413.       for(i=0;i<CScan->NumberComponents;i++)  /* Close all components */
  414.     {
  415.       InstallIob(i);
  416.       CloseIob();
  417.     }
  418.     }
  419.   WriteEoi();                              /* All finished, Write eoi */
  420. }
  421.  
  422. /*BFUNC
  423.  
  424. JpegQuantizationFrame() sets up the default quantization matrices to be
  425. used in the scan. Not to be used with user-specified quantization.
  426.  
  427. EFUNC*/
  428.  
  429. void JpegQuantizationFrame()
  430. {
  431.   BEGIN("JpegQuantizationFrame");
  432.   int i;
  433.  
  434.   if (CFrame->Q)                    /* if Q  rescale quantization matrices */
  435.     CImage->QuantizationMatrices[0] =
  436.       ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,LuminanceQuantization);
  437.   else
  438.     CImage->QuantizationMatrices[0] = LuminanceQuantization;
  439.  
  440.   CScan->sq[CScan->NumberQTablesSend++] = 0; /* Queue luminance to send */
  441.   if (CFrame->GlobalNumberComponents>1)
  442.     {
  443.       if (CFrame->Q)                 /* rescale quantization matrices */
  444.     CImage->QuantizationMatrices[1] =
  445.       ScaleMatrix(CFrame->Q,Q_PRECISION,LargeQ,ChrominanceQuantization);
  446.       else
  447.     CImage->QuantizationMatrices[1] = ChrominanceQuantization;
  448.       CScan->sq[CScan->NumberQTablesSend++] = 1; /* Queue table to send */
  449.     }
  450.   for(i=0;i<CFrame->GlobalNumberComponents;i++)
  451.     {
  452.       if (i%ScanComponentThreshold)
  453.     CFrame->tq[CFrame->cn[i]]=1; /* chrominance q for non-primaries */
  454.       else
  455.     CFrame->tq[CFrame->cn[i]]=0; /* luminance q starts each scan */
  456.     }
  457. }
  458.  
  459. /*BFUNC
  460.  
  461. JpegDefaultHuffmanScan() creates the default tables for baseline use.
  462.  
  463. EFUNC*/
  464.  
  465. void JpegDefaultHuffmanScan()
  466. {
  467.   BEGIN("JpegDefaultScan");
  468.   int i;
  469.  
  470.   if (CFrame->DataPrecision>8)
  471.     {
  472.       WHEREAMI();
  473.       printf("Default tables attempted with precision > 8.\n");
  474.       exit(ERROR_BOUNDS);
  475.     }
  476.   MakeXhuff();                      /* Make luminance DC Huffman */
  477.   MakeEhuff();
  478.   SpecifiedHuffman(LuminanceDCBits,LuminanceDCValues);
  479.   SetDCHuffman(0);
  480.   MakeXhuff();                      /* Make luminance AC Huffman */
  481.   MakeEhuff();
  482.   SpecifiedHuffman(LuminanceACBits,LuminanceACValues);
  483.   SetACHuffman(0);
  484.   MakeXhuff();
  485.   MakeEhuff();
  486.   CScan->td[0] = 0;
  487.   CScan->ta[0] = 0;
  488.   CScan->sa[CScan->NumberACTablesSend++] = 0;  /* Queue to transmit table */
  489.   CScan->sd[CScan->NumberDCTablesSend++] = 0;
  490.   if(CScan->NumberComponents>1)     /* Make chrominance Huffman tables */
  491.     {                               /* Only if necessary */
  492.       SpecifiedHuffman(ChrominanceDCBits,ChrominanceDCValues);
  493.       SetDCHuffman(1);
  494.       MakeXhuff();
  495.       MakeEhuff();
  496.       SpecifiedHuffman(ChrominanceACBits,ChrominanceACValues);
  497.       SetACHuffman(1);
  498.       for(i=1;i<CScan->NumberComponents;i++)
  499.     {
  500.       CScan->td[i] = 1;
  501.       CScan->ta[i] = 1;
  502.     }
  503.       CScan->sa[CScan->NumberACTablesSend++] = 1;
  504.       CScan->sd[CScan->NumberDCTablesSend++] = 1;
  505.       CImage->NumberACTables = MAX(CImage->NumberACTables,2);
  506.       CImage->NumberDCTables = MAX(CImage->NumberDCTables,2);
  507.     }
  508.   else
  509.     {
  510.       CImage->NumberACTables = MAX(CImage->NumberACTables,1);
  511.       CImage->NumberDCTables = MAX(CImage->NumberDCTables,1);
  512.     }
  513. }
  514.  
  515. /*BFUNC 
  516.  
  517. JpegFrequencyScan() assembles the frequency statistics for the given
  518. scan, making one AC Freq, DC Freq statistic per component specified.
  519. This function should be used before making custom quantization tables.
  520.  
  521. EFUNC*/
  522.  
  523. void JpegFrequencyScan()
  524. {
  525.   BEGIN("JpegFrequencyScan");
  526.   int i,j,h,v,dohf,dovf;
  527.   int input[64],output[64];
  528.   int DCTBound,DCTShift;
  529.  
  530.   InstallIob(0);                 /* Zero out for fast single-component */
  531.   InstallPrediction(0);          /* operation. */
  532.   InstallFrequency(0); 
  533.   CheckScan();
  534.   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
  535.   ClearFrameFrequency();
  536.   ResetCodec();
  537.   DCTBound = ((CFrame->DataPrecision>8)?16383:1023);
  538.   DCTShift = ((CFrame->DataPrecision>8)?2048:128);
  539.   for(i=0;i<NumberMDU;i++)         /* Do for all MDU in image */
  540.     {
  541.       if ( i && (CFrame->ResyncInterval))
  542.     {
  543.       if (!(i % CFrame->ResyncInterval)) /* Resync the codec */
  544.         ResetCodec();
  545.     }
  546.       for(j=0;j<CScan->NumberComponents;j++)
  547.     {
  548.       InstallIob(j);
  549.       InstallPrediction(j);    /* Install statistics tables */
  550.       InstallFrequency(j);
  551.       if (CScan->NumberComponents==1)
  552.         dohf=dovf=1;
  553.       else
  554.         {
  555.           dohf = CFrame->hf[CScan->ci[j]];
  556.           dovf = CFrame->vf[CScan->ci[j]];
  557.         }
  558.       for(v=0;v<dovf;v++)  /* Do encoding */
  559.         {                                      /* and accum. stats */
  560.           for(h=0;h<dohf;h++)
  561.         {
  562.           ReadBlock(input);
  563.           PreshiftDctMatrix(input,DCTShift);
  564.           DefaultDct(input,output);
  565.           BoundDctMatrix(output,DCTBound);
  566.           Quantize(output,
  567.                CImage->
  568.                QuantizationMatrices[CFrame->
  569.                         tq[CScan->ci[j]]]);
  570.           ZigzagMatrix(output,input);
  571.           FrequencyDC(*input);           /* Freq accumulates */
  572.           FrequencyAC(input);            /* stats w/o encoding */
  573.         }
  574.         }
  575.     }
  576.     }
  577.   for(i=0;i<CScan->NumberComponents;i++)  /* Rewind to start */
  578.     {
  579.       InstallIob(i);
  580.       RewindIob();
  581.     }
  582. }
  583.  
  584. /*BFUNC
  585.  
  586. JpegCustomScan() assembles custom Huffman tables for the input.
  587. It defaults to baseline unless FULLHUFFMAN flag is set.
  588.  
  589. EFUNC*/
  590.  
  591. void JpegCustomScan(flags)
  592.      int flags;
  593. {
  594.   BEGIN("JpegCustomScan");
  595.   int i,Sumbits;
  596.   
  597.   if ((GetFlag(CImage->JpegMode,J_FULLHUFFMAN)) ||
  598.       (CScan->NumberComponents < 3))
  599.     {
  600.       for(i=0;i<CScan->NumberComponents;i++)
  601.     {
  602.       if (GetFlag(flags,CUSTOM_DO_DC))
  603.         {
  604.           MakeXhuff();
  605.           MakeEhuff();
  606.           MakeHuffman(CScan->DCFrequency[i]);
  607.           SetDCHuffman(i);
  608.           CScan->td[i] = i;
  609.           CScan->sd[CScan->NumberDCTablesSend++] = i;
  610.         }
  611.       if (GetFlag(flags,CUSTOM_DO_AC))
  612.         {
  613.           MakeXhuff();
  614.           MakeEhuff();
  615.           MakeHuffman(CScan->ACFrequency[i]);
  616.           SetACHuffman(i);
  617.           CScan->ta[i] = i;
  618.           CScan->sa[CScan->NumberACTablesSend++] = i;
  619.         }
  620.       InstallIob(i);
  621.       RewindIob();
  622.     }
  623.       CImage->NumberACTables = MAX(CImage->NumberACTables,
  624.                    CScan->NumberComponents);
  625.       CImage->NumberDCTables = MAX(CImage->NumberDCTables,
  626.                    CScan->NumberComponents);
  627.     }
  628.   else
  629.     {
  630.       if (GetFlag(flags,CUSTOM_DO_DC))
  631.     {
  632.       MakeXhuff();                   /* 0 Component has custom Huffman */
  633.       MakeEhuff();
  634.       MakeHuffman(CScan->DCFrequency[0]);
  635.       SetDCHuffman(0);
  636.       CScan->td[0] = 0;              /* 0 component uses tables 0 */
  637.       CScan->sd[CScan->NumberDCTablesSend++] = 0; /* Queue to send */
  638.     }
  639.       if (GetFlag(flags,CUSTOM_DO_AC))
  640.     {
  641.       MakeXhuff();
  642.       MakeEhuff();
  643.       MakeHuffman(CScan->ACFrequency[0]);
  644.       SetACHuffman(0);
  645.       CScan->ta[0] = 0;
  646.       CScan->sa[CScan->NumberACTablesSend++] = 0; /* Queue table send */
  647.     }
  648.       if (CScan->NumberComponents > 1)
  649.     {
  650.       if (GetFlag(flags,CUSTOM_DO_DC))
  651.         {
  652.           for(i=2;i<CScan->NumberComponents;i++) /* Rest share Huffman*/
  653.         {                                    /* Accum. frequencies */
  654.           AddFrequency(CScan->DCFrequency[1],CScan->DCFrequency[i]);
  655.         }
  656.           MakeXhuff();
  657.           MakeEhuff();
  658.           MakeHuffman(CScan->DCFrequency[1]);
  659.           SetDCHuffman(1);
  660.           for(i=1;i<CScan->NumberComponents;i++) /* Rest use table 1 */
  661.         CScan->td[i] = 1;
  662.           CScan->sd[CScan->NumberDCTablesSend++] = 1;/* Queue to send */
  663.         }
  664.       if (GetFlag(flags,CUSTOM_DO_AC))
  665.         {
  666.           for(i=2;i<CScan->NumberComponents;i++) /*Accum. frequencies */
  667.         {
  668.           AddFrequency(CScan->ACFrequency[1],CScan->ACFrequency[i]);
  669.         }
  670.           MakeXhuff();
  671.           MakeEhuff();
  672.           MakeHuffman(CScan->ACFrequency[1]);
  673.           SetACHuffman(1);
  674.           for(i=1;i<CScan->NumberComponents;i++) /* Rest use table 1 */
  675.         CScan->ta[i] = 1;
  676.           CScan->sa[CScan->NumberACTablesSend++] = 1;  /* Queue to send */
  677.         }
  678.       CImage->NumberACTables = MAX(CImage->NumberACTables,2);/*reset */
  679.       CImage->NumberDCTables = MAX(CImage->NumberDCTables,2);/* limits */
  680.     }
  681.       else
  682.     {
  683.       CImage->NumberACTables = MAX(CImage->NumberACTables,1); /* Reset */
  684.       CImage->NumberDCTables = MAX(CImage->NumberDCTables,1); /*  limits */
  685.     }
  686.     }
  687.   if (HuffmanTrace)     /* If trace flag, then dump out frequency tables */
  688.     {
  689.       Sumbits = 0;
  690.       for(i=0;i<CImage->NumberACTables;i++)
  691.     {
  692.       WHEREAMI();
  693.       printf("AC Code Frequency: Table %d\n",i);
  694.       PrintACEhuff(i);
  695.       Sumbits += SizeACEhuff(i);
  696.     }
  697.       for(i=0;i<CImage->NumberDCTables;i++)
  698.     {
  699.       WHEREAMI();
  700.       printf("DC Code Frequency: Table %d\n",i);
  701.       PrintDCEhuff(i);
  702.       Sumbits +=  SizeDCEhuff(i);
  703.     }
  704.       WHEREAMI();
  705.       printf("Total bits: %d  bytes: %d\n",
  706.          Sumbits,(Sumbits+7)/8);
  707.     }
  708. }
  709.  
  710. /*BFUNC
  711.  
  712. JpegEncodeScan() encodes the scan that is given to it. We assume that
  713. the quantization and the Huffman tables have already been specified.
  714.  
  715. EFUNC*/
  716.  
  717. void JpegEncodeScan()
  718. {
  719.   BEGIN("JpegEncodeScan");
  720.   int i,j,h,v,dohf,dovf;
  721.   int input[64],output[64];
  722.   int DCTBound,DCTShift;
  723.   
  724.   InstallIob(0);
  725.   CheckScan();
  726.   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
  727.   ClearFrameFrequency();
  728.   ResetCodec();
  729.   DCTBound = ((CFrame->DataPrecision>8)?16383:1023);
  730.   DCTShift = ((CFrame->DataPrecision>8)?2048:128);
  731.   ResyncCount=0;                /* Reset the resync counter for every scan */
  732.   if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */
  733.     {                           /* into according Resync interval */
  734.       if  (!(CFrame->ResyncInterval))
  735.     WriteDnl();  /* Automatically write a dnl if no resync is enabled.*/
  736.       else                      /* If DNL > MDU, then put in last resync */
  737.     CFrame->InsertDnl = MAX(CFrame->InsertDnl,      /* interval */
  738.                 NumberMDU/CFrame->ResyncInterval);
  739.     }
  740.   WriteSos();                  /* Start of Scan */
  741.   for(i=0;i<NumberMDU;i++)
  742.     {
  743.       if ( i && (CFrame->ResyncInterval))
  744.     {
  745.       if (!(i % CFrame->ResyncInterval)) /* Check for resync */
  746.         {
  747.           if ((i/CFrame->ResyncInterval)==CFrame->InsertDnl)
  748.         {
  749.           WriteDnl();                /* If resync matches use DNL */
  750.           CFrame->InsertDnl=0;       /* Mission accomplished. */
  751.         }
  752.           WriteResync();                 /* Write resync */
  753.           ResetCodec();
  754.         }
  755.     }
  756.       for(j=0;j<CScan->NumberComponents;j++)
  757.     {
  758.       if (Loud > MUTE)
  759.         {
  760.           WHEREAMI();
  761.           printf("[Pass 2 [Component:MDU] [%d:%d]]\n",j,i);
  762.         }
  763.       InstallIob(j);                    /* Install component j */
  764.       InstallPrediction(j);
  765.       if (CScan->NumberComponents==1)
  766.         dohf=dovf=1;
  767.       else
  768.         {
  769.           dohf = CFrame->hf[CScan->ci[j]];
  770.           dovf = CFrame->vf[CScan->ci[j]];
  771.         }
  772.       for(v=0;v<dovf;v++)  /* loop thru MDU */
  773.         {
  774.           for(h=0;h<dohf;h++)
  775.         {
  776.           ReadBlock(input);                /* Read in */
  777.           if (Loud > WHISPER)
  778.             {
  779.               WHEREAMI();
  780.               printf("Raw input:\n");
  781.               PrintMatrix(input);
  782.             }
  783.           PreshiftDctMatrix(input,DCTShift);        /* Shift */
  784.           DefaultDct(input,output);        /* DCT */
  785.           BoundDctMatrix(output,DCTBound); /* Bound, limit */
  786.           Quantize(output,                 /* Quantize */
  787.                CImage->
  788.                QuantizationMatrices[CFrame->
  789.                         tq[CScan->ci[j]]]);
  790.           ZigzagMatrix(output,input);      /* Zigzag trace */
  791.           if (Loud > TALK)
  792.             {
  793.               WHEREAMI();
  794.               printf("Cooked Output:\n");
  795.               PrintMatrix(input);
  796.             }
  797.           UseDCHuffman(CScan->td[j]);
  798.           EncodeDC(*input);               /* Encode DC component */
  799.           UseACHuffman(CScan->ta[j]);
  800.           EncodeAC(input);                /* Encode AC component */
  801.         }
  802.         }
  803.     }
  804.     }
  805.   if (CFrame->InsertDnl==-2)    /* -2 is automatic DNL insertion */
  806.     {
  807.       WriteDnl();                 /* Put DNL here */
  808.       CFrame->InsertDnl=0;
  809.     }
  810.   for(i=0;i<CScan->NumberComponents;i++)          /* Rewind to start */
  811.     {
  812.       InstallIob(i);
  813.       RewindIob();
  814.     }
  815. }
  816.  
  817. /*BFUNC
  818.  
  819. JpegLosslessFrequencyScan() accumulates the frequencies into the DC
  820. frequency index.
  821.  
  822. EFUNC*/
  823.  
  824. void JpegLosslessFrequencyScan()
  825. {
  826.   BEGIN("JpegLosslessFrequencyScan");
  827.   int x,y,j,h,v,px;
  828.   int height,width,horfreq,value;
  829.   int MaxElem,CurrentElem,NumberElem;
  830.   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
  831.   int *input;
  832.  
  833.   CheckScan();
  834.   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
  835.     {
  836.       InstallIob(j);
  837.       RewindIob();
  838.     }
  839.   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
  840.     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
  841.   else
  842.     {
  843.       MaxElem= LOSSLESSBUFFERSIZE/
  844.     ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
  845.       for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
  846.     {
  847.       x=LOSSLESSBUFFERSIZE/
  848.         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
  849.       if (x < MaxElem) MaxElem=x;
  850.     }
  851.     }
  852.   CScan->SSS=LosslessPredictorType;
  853.   CScan->SAL=PointTransform;
  854.   ClearFrameFrequency();
  855.   InstallIob(0);             /* Set up values for fast non-interleaved mode */
  856.   InstallFrequency(0);
  857.   if (CScan->NumberComponents==1)
  858.     height=horfreq=1;
  859.   else
  860.     {
  861.       height=CFrame->vf[CScan->ci[0]];
  862.       horfreq=CFrame->hf[CScan->ci[0]];
  863.     }
  864.   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
  865.   CurrentMDU=0;
  866.   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
  867.     {
  868.       WHEREAMI();
  869.       printf("Resync Interval not an integer multiple of MDU's wide.\n");
  870.       printf("Proceeding anyways.\n");
  871.       if (MaxElem>=CFrame->ResyncInterval)
  872.     MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
  873.       else
  874.     MaxElem=1;                            /* Can't proceed quickly */
  875.     }
  876.   CurrentElem=NumberElem=0;
  877.   for(y=0;y<CScan->MDUHigh;y++)
  878.     {
  879.       for(x=0;x<CScan->MDUWide;x++)
  880.     {
  881.       if (CurrentMDU && (CFrame->ResyncInterval))
  882.         {
  883.           if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */
  884.         {
  885.           UseType=1;                     /* Reset codec */
  886.           for(j=0;j<CScan->NumberComponents;j++)
  887.             {
  888.               InstallIob(j); 
  889.               LineResetBuffers();
  890.             }
  891.         }
  892.         }
  893.       if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */
  894.         {
  895.           UseType=2;                           /* Start of line */
  896.           StartofLine=1;                       /* uses top pel predictor */
  897.         }
  898.       CurrentElem++;
  899.       if (CurrentElem>=NumberElem)
  900.         {
  901.           NumberElem = MIN((CScan->MDUWide-x),MaxElem);
  902.           CurrentElem=0;
  903.           for(j=0;j<CScan->NumberComponents;j++)
  904.         {
  905.           InstallIob(j);                    /* Install component j */
  906.           ReadLine(NumberElem,              /* Read in some elements*/
  907.                CScan->LosslessBuffer[j]); 
  908.         }
  909.         }
  910.       if (CScan->NumberComponents==1)
  911.         {
  912.           width=horfreq*NumberElem+1;
  913.           input = &CScan->LosslessBuffer[0][CurrentElem];
  914.           if (Loud > NOISY)
  915.         {
  916.           WHEREAMI();
  917.           printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n",
  918.              0,CurrentMDU,NumberMDU);
  919.         }
  920.           switch(UseType) /* Same as lossless coding predictor*/
  921.         {
  922.         case 1:
  923.           px = input[width];
  924.           break;
  925.         case 2:
  926.           px = input[1];
  927.           break;
  928.         case 3:
  929.           px = input[0];
  930.           break;
  931.         case 4:
  932.           px = input[width] + input[1] - input[0];
  933.           break;
  934.         case 5:
  935.           px = input[width] + ((input[1] - input[0])>>1);
  936.           break;
  937.         case 6:
  938.           px = input[1] + ((input[width] - input[0])>>1);
  939.           break;
  940.         case 7:
  941.           px = (input[1]+input[width])>>1;  /* No rounding */
  942.           break;
  943.         default:
  944.           WHEREAMI();
  945.           printf("Lossless mode %d not supported.\n",UseType);
  946.           break;
  947.         }
  948.           value=input[width+1]-px;
  949.           if (Loud > NOISY)
  950.         printf("IN=%d  PX=%d  FRE: %d\n",
  951.                input[width+1],px,value);
  952.           LosslessFrequencyDC(value); 
  953.         }
  954.       else
  955.         {
  956.           for(j=0;j<CScan->NumberComponents;j++)
  957.         {
  958.           if (Loud > NOISY)
  959.             {
  960.               WHEREAMI();
  961.               printf("[Pass 1 [Component:MDU:Total] [%d:%d:%d]]\n",
  962.                  j,CurrentMDU,NumberMDU);
  963.             }
  964.           InstallFrequency(j);
  965.           height=CFrame->vf[CScan->ci[j]];
  966.           horfreq=CFrame->hf[CScan->ci[j]];
  967.           width=horfreq*NumberElem+1;
  968.           input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
  969.           for(v=1;v<=height;v++) 
  970.             {
  971.               for(h=1;h<=horfreq;h++)
  972.             {
  973.               switch(UseType) /* lossless coding predictor*/
  974.                 {
  975.                 case 1:
  976.                   px = input[(v*(width))+h-1];
  977.                   break;
  978.                 case 2:
  979.                   px = input[((v-1)*(width))+h];
  980.                   break;
  981.                 case 3:
  982.                   px = input[((v-1)*(width))+h-1];
  983.                   break;
  984.                 case 4:
  985.                   px = input[(v*(width))+h-1] +
  986.                 input[((v-1)*(width))+h] -
  987.                   input[((v-1)*(width))+h-1];
  988.                   break;
  989.                 case 5:
  990.                   px = input[(v*(width))+h-1] +
  991.                 ((input[((v-1)*(width))+h] -
  992.                  input[((v-1)*(width))+h-1])>>1);
  993.                   break;
  994.                 case 6:
  995.                   px = input[((v-1)*(width))+h] +
  996.                 ((input[(v*(width))+h-1] -
  997.                  input[((v-1)*(width))+h-1])>>1);
  998.                   break;
  999.                 case 7:
  1000.                   px = (input[((v-1)*(width))+h] +
  1001.                     input[(v*(width))+h-1])>>1;
  1002.                   break;
  1003.                 default:
  1004.                   WHEREAMI();
  1005.                   printf("Lossless mode: %d not supported.\n",
  1006.                      UseType);
  1007.                   break;
  1008.                 }
  1009.               value=input[(v*(width))+h]-px;
  1010.               if (Loud > NOISY)
  1011.                 printf("IN=%d  PX=%d  FRE: %d\n",
  1012.                    input[(v*(width))+h],px,value);
  1013.               LosslessFrequencyDC(value); 
  1014.             }
  1015.             }
  1016.         }
  1017.         }
  1018.       CurrentMDU++;
  1019.       if (StartofLine)
  1020.         {
  1021.           UseType=CScan->SSS;
  1022.           StartofLine=0;
  1023.         }
  1024.     }
  1025.     }
  1026.   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
  1027.     {
  1028.       InstallIob(j);
  1029.       RewindIob();
  1030.     }
  1031. }
  1032.  
  1033. /*BFUNC
  1034.  
  1035. JpegEncodeLosslessScan() encodes the scan that is given to it by lossless
  1036. techniques. The Huffman table should already be specified.
  1037.  
  1038. EFUNC*/
  1039.  
  1040. void JpegLosslessEncodeScan()
  1041. {
  1042.   BEGIN("JpegEncodeLosslessScan");
  1043.   int x,y,j,h,v,px;
  1044.   int height,width,horfreq,value;
  1045.   int MaxElem,CurrentElem,NumberElem;
  1046.   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
  1047.   int *input;
  1048.   
  1049.   CheckScan();
  1050.   for(j=0;j<CScan->NumberComponents;j++)    /* Important to rewind to start */
  1051.     {                                       /* for lossless coding... */
  1052.       InstallIob(j);
  1053.       RewindIob();
  1054.     }
  1055.   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
  1056.     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
  1057.   else
  1058.     {
  1059.       MaxElem= LOSSLESSBUFFERSIZE/
  1060.     ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
  1061.       for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
  1062.     {
  1063.       x=LOSSLESSBUFFERSIZE/
  1064.         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
  1065.       if (x < MaxElem) MaxElem=x;
  1066.     }
  1067.     }
  1068.   CScan->SSS=LosslessPredictorType;
  1069.   CScan->SAL=PointTransform;
  1070.   InstallIob(0);
  1071.   UseDCHuffman(CScan->td[0]);          /* Install DC table */
  1072.   if (CScan->NumberComponents==1)
  1073.     height=horfreq=1;
  1074.   else
  1075.     {
  1076.       height=CFrame->vf[CScan->ci[0]];
  1077.       horfreq=CFrame->hf[CScan->ci[0]];
  1078.     }
  1079.   NumberMDU = CScan->MDUWide*CScan->MDUHigh;
  1080.   ResyncCount=0;                /* Reset the resync counter for every scan */
  1081.   if (CFrame->InsertDnl>0) /* If DNL is greater than 0, insert */
  1082.     {                           /* into according Resync interval */
  1083.       if  (!(CFrame->ResyncInterval))
  1084.     WriteDnl();  /* Automatically write a dnl if no resync is enabled.*/
  1085.       else                      /* If DNL > MDU, then put in last resync */
  1086.     CFrame->InsertDnl = MAX(CFrame->InsertDnl,         /* interval */
  1087.                 NumberMDU/CFrame->ResyncInterval);
  1088.     }
  1089.   WriteSos();                  /* Start of Scan */
  1090.   CurrentMDU=0;
  1091.   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
  1092.     {
  1093.       WHEREAMI();
  1094.       printf("Resync Interval not an integer multiple of MDU's wide.\n");
  1095.       printf("Proceeding anyways.\n");
  1096.       if (MaxElem>=CFrame->ResyncInterval)
  1097.     MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
  1098.       else
  1099.     MaxElem=1;                            /* Can't proceed quickly */
  1100.     }
  1101.   CurrentElem=NumberElem=0;
  1102.   for(y=0;y<CScan->MDUHigh;y++)
  1103.     {
  1104.       for(x=0;x<CScan->MDUWide;x++)
  1105.     {
  1106.       if (CurrentMDU && (CFrame->ResyncInterval))
  1107.         {
  1108.           if (!(CurrentMDU % CFrame->ResyncInterval)) /* Check resync */
  1109.         {
  1110.           if ((CurrentMDU/CFrame->ResyncInterval)==CFrame->InsertDnl)
  1111.             {
  1112.               WriteDnl();              /* If resync matches use DNL */
  1113.               CFrame->InsertDnl=0;     /* Mission accomplished. */
  1114.             }
  1115.           WriteResync();                 /* Write resync */
  1116.           UseType=1;                     /* Reset codec */
  1117.           for(j=0;j<CScan->NumberComponents;j++)
  1118.             {
  1119.               InstallIob(j); 
  1120.               LineResetBuffers();
  1121.             }
  1122.         }
  1123.         }
  1124.       if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU)) /* Reset CScan type */
  1125.         {
  1126.           UseType=2;                           /* Start of line */
  1127.           StartofLine=1;                       /* uses top pel predictor */
  1128.         }
  1129.       CurrentElem++;
  1130.       if (CurrentElem>=NumberElem)
  1131.         {
  1132.           NumberElem = MIN((CScan->MDUWide-x),MaxElem);
  1133.           CurrentElem=0;
  1134.           for(j=0;j<CScan->NumberComponents;j++)
  1135.         {
  1136.           InstallIob(j);                    /* Install component j */
  1137.           ReadLine(NumberElem,              /* Read in some elements*/
  1138.                CScan->LosslessBuffer[j]); 
  1139.         }
  1140.         }
  1141.       if (CScan->NumberComponents==1)
  1142.         {
  1143.           if (Loud > MUTE)
  1144.         {
  1145.           WHEREAMI();
  1146.           printf("[Pass 2 [Component:MDU:Total] [%d:%d:%d]]\n",
  1147.              0,CurrentMDU,NumberMDU);
  1148.         }
  1149.           input = &CScan->LosslessBuffer[0][CurrentElem];
  1150.           width=horfreq*NumberElem+1;
  1151.           switch(UseType) /* Same as lossless coding predictor*/
  1152.         {
  1153.         case 1:
  1154.           px = input[width];
  1155.           break;
  1156.         case 2:
  1157.           px = input[1];
  1158.           break;
  1159.         case 3:
  1160.           px = input[0];
  1161.           break;
  1162.         case 4:
  1163.           px = input[width] + input[1] - input[0];
  1164.           break;
  1165.         case 5:
  1166.           px = input[width] + ((input[1] - input[0])>>1);
  1167.           break;
  1168.         case 6:
  1169.           px = input[1] + ((input[width] - input[0])>>1);
  1170.           break;
  1171.         case 7:
  1172.           px = (input[1] + input[width])>>1;  /* No rounding */
  1173.           break;
  1174.         default:
  1175.           WHEREAMI();
  1176.           printf("Lossless mode %d not supported.\n",UseType);
  1177.           break;
  1178.         }
  1179.           value=input[width+1]-px;
  1180.           if (Loud > MUTE)
  1181.         printf("IN=%d  PX=%d  FRE: %d\n",
  1182.                input[width+1],px,value);
  1183.           LosslessEncodeDC(value); 
  1184.         }
  1185.       else
  1186.         {
  1187.           for(j=0;j<CScan->NumberComponents;j++)
  1188.         {
  1189.           if (Loud > MUTE)
  1190.             {
  1191.               WHEREAMI();
  1192.               printf("[Pass 2 [Component:MDU] [%d:%d]]\n",
  1193.                  j,CurrentMDU);
  1194.             }
  1195.           height=CFrame->vf[CScan->ci[j]];
  1196.           horfreq=CFrame->hf[CScan->ci[j]];
  1197.           width=horfreq*NumberElem+1;
  1198.           input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
  1199.           UseDCHuffman(CScan->td[j]);
  1200.           for(v=1;v<=height;v++) 
  1201.             {
  1202.               for(h=1;h<=horfreq;h++)
  1203.             {
  1204.               switch(UseType)   /* Same as lossless predictor*/
  1205.                 {
  1206.                 case 1:
  1207.                   px = input[(v*(width))+h-1];
  1208.                   break;
  1209.                 case 2:
  1210.                   px = input[((v-1)*(width))+h];
  1211.                   break;
  1212.                 case 3:
  1213.                   px = input[((v-1)*(width))+h-1];
  1214.                   break;
  1215.                 case 4:
  1216.                   px = input[(v*(width))+h-1] +
  1217.                 input[((v-1)*(width))+h] -
  1218.                   input[((v-1)*(width))+h-1];
  1219.                   break;
  1220.                 case 5:
  1221.                   px = input[(v*(width))+h-1] +
  1222.                 ((input[((v-1)*(width))+h] -
  1223.                   input[((v-1)*(width))+h-1])>>1);
  1224.                   break;
  1225.                 case 6:
  1226.                   px = input[((v-1)*(width))+h] +
  1227.                 ((input[(v*(width))+h-1] -
  1228.                   input[((v-1)*(width))+h-1])>>1);
  1229.                   break;
  1230.                 case 7:
  1231.                   px = (input[((v-1)*(width))+h] +
  1232.                     input[(v*(width))+h-1])>>1;
  1233.                   break;
  1234.                 default:
  1235.                   WHEREAMI();
  1236.                   printf("Lossless mode %d not supported.\n",
  1237.                      UseType);
  1238.                   break;
  1239.                 }
  1240.               value=input[(v*(width))+h]-px;
  1241.               if (Loud > MUTE)
  1242.                 {
  1243.                   printf("IN=%d  PX=%d  ENC: %d\n",
  1244.                      input[(v*(width))+h],px,value);
  1245.                 }
  1246.               LosslessEncodeDC(value); /* Encode as DC component */
  1247.             }
  1248.             }
  1249.         }
  1250.         }
  1251.       CurrentMDU++;
  1252.       if (StartofLine)
  1253.         {
  1254.           UseType=CScan->SSS;
  1255.           StartofLine=0;
  1256.         }
  1257.     }
  1258.     }
  1259.   if (CFrame->InsertDnl==-2)    /* -2 is automatic DNL insertion */
  1260.     {
  1261.       WriteDnl();
  1262.       CFrame->InsertDnl=0;
  1263.     }
  1264.  
  1265.   for(j=0;j<CScan->NumberComponents;j++)          /* Rewind to start */
  1266.     {
  1267.       InstallIob(j);
  1268.       RewindIob();
  1269.     }
  1270. }
  1271.  
  1272. /*BFUNC
  1273.  
  1274. JpegDecodeFrame(general,)
  1275.      ) is used to decode a file. In general; is used to decode a file. In general, CFrame should
  1276. hold just enough information to set up the file structure; that is,
  1277. which file is to be opened for what component.
  1278.  
  1279. EFUNC*/
  1280.  
  1281. static void JpegDecodeFrame()
  1282. {
  1283.   BEGIN("JpegDecodeFrame");
  1284.   int i;
  1285.   
  1286.   sropen(CImage->StreamFileName,0);   /* Zero index */
  1287.   if (ScreenAllMarker() < 0)          /* Do all markers pending */
  1288.     {
  1289.       WHEREAMI();
  1290.       printf("No initial marker found!\n");
  1291.       exit(-1);
  1292.     }
  1293.   while(1)
  1294.     {
  1295.       if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
  1296.     {
  1297.       if (CurrentMDU >= NumberMDU) /* If all decoded */
  1298.         {
  1299.           if (Notify)             /* Print statistics */
  1300.         {
  1301.           printf("> GW:%d  GH:%d  R:%d\n",
  1302.              CFrame->GlobalWidth,
  1303.              CFrame->GlobalHeight,
  1304.              CFrame->ResyncInterval);
  1305.         }
  1306.           for(i=0;i<CScan->NumberComponents;i++)  /* Print Scan info */
  1307.         {
  1308.           if (Notify)
  1309.             {
  1310.               printf(">> C:%d  N:%s  W:%d  H:%d  hf:%d  vf:%d\n",
  1311.                  CScan->ci[i],
  1312.                  CFrame->ComponentFileName[CScan->ci[i]],
  1313.                  CFrame->Width[CScan->ci[i]],
  1314.                  CFrame->Height[CScan->ci[i]],
  1315.                  CFrame->hf[CScan->ci[i]],
  1316.                  CFrame->vf[CScan->ci[i]]);
  1317.             }
  1318.           InstallIob(i);
  1319.           FlushIob();                        /* Close image files */
  1320.           SeekEndIob();
  1321.           CloseIob();
  1322.         }
  1323.           CurrentMDU=0;
  1324.           if (ScreenAllMarker()<0)            /* See if any more images*/
  1325.         {
  1326.           WHEREAMI();
  1327.           printf("No trailing marker found!\n");
  1328.           exit(-1);
  1329.         }
  1330.           if ((EndofFile)||(EndofImage))      /* Nothing, then return */
  1331.         {
  1332.           srclose();
  1333.           break;
  1334.         }
  1335.         }
  1336.     }
  1337.       if (CFrame->Type==3)
  1338.     JpegLosslessDecodeScan();
  1339.       else
  1340.     JpegDecodeScan();
  1341.     }
  1342. }
  1343.  
  1344. /*BFUNC
  1345.  
  1346. JpegLosslessDecodeScan() is used to losslessly decode a portion of the
  1347. image called the scan.  This routine uses the internal lossless
  1348. buffers to reduce the overhead in writing.  However, one must note
  1349. that the overhead is mostly in the Huffman decoding.
  1350.  
  1351. EFUNC*/
  1352.  
  1353. static void JpegLosslessDecodeScan()
  1354. {
  1355.   BEGIN("JpegLosslessDecodeScan");
  1356.   int j,v,h,value,px;
  1357.   int height,horfreq,width;
  1358.   int MaxElem,CurrentElem,NumberElem;
  1359.   int StartofLine=1,UseType=1;              /* Start with type 1 coding */
  1360.   int *input;
  1361.  
  1362.   PointTransform=CScan->SAL;
  1363.   for(j=0;j<CScan->NumberComponents;j++)    /* Important to rewind to start */
  1364.     {                                       /* for lossless coding... */
  1365.       InstallIob(j);
  1366.       RewindIob();
  1367.     }
  1368.   if (CScan->NumberComponents==1)       /* Calculate maximum number of */
  1369.     MaxElem= LOSSLESSBUFFERSIZE/4;      /* elements can be loaded in */
  1370.   else
  1371.     {
  1372.       MaxElem= LOSSLESSBUFFERSIZE/
  1373.     ((CFrame->vf[CScan->ci[0]]+1)*(CFrame->hf[CScan->ci[0]]+1));
  1374.       for(j=1;j<CScan->NumberComponents;j++)          /* Rewind to start */
  1375.     {
  1376.       v=LOSSLESSBUFFERSIZE/
  1377.         ((CFrame->vf[CScan->ci[j]]+1)*(CFrame->hf[CScan->ci[j]]+1));
  1378.       if (v < MaxElem) MaxElem=v;
  1379.     }
  1380.     }
  1381.   InstallIob(0);
  1382.   UseDCHuffman(CScan->td[0]);          /* Install DC table */
  1383.   if (CScan->NumberComponents==1)
  1384.     height=horfreq=1;
  1385.   else
  1386.     {
  1387.       height=CFrame->vf[CScan->ci[0]];
  1388.       horfreq=CFrame->hf[CScan->ci[0]];
  1389.     }
  1390.   if ((CFrame->ResyncInterval)&&(CFrame->ResyncInterval % CScan->MDUWide))
  1391.     {
  1392.       WHEREAMI();
  1393.       printf("Resync Interval not an integer multiple of MDU's wide.\n");
  1394.       printf("Proceeding anyways.\n");
  1395.       if (MaxElem>=CFrame->ResyncInterval)
  1396.     MaxElem=CFrame->ResyncInterval;       /* Reduce to resync interval */
  1397.       else
  1398.     MaxElem=1;                            /* Can't proceed quickly */
  1399.     }
  1400.   CurrentElem=NumberElem=0;
  1401.   while(1)
  1402.     {
  1403.       if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide)))
  1404.     {
  1405.       if (CheckMarker()==0xdc)
  1406.         ScreenMarker();
  1407.     }
  1408.       if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
  1409.     {
  1410.       if (CurrentMDU >= NumberMDU) /* If all decoded */
  1411.         return;
  1412.     }
  1413.  
  1414.       if (CFrame->ResyncInterval)                /* Flag to decoder stream */
  1415.     ResyncEnable = 1;
  1416.       if (CurrentMDU && (CFrame->ResyncInterval))
  1417.     {                                    /* If resync interval */
  1418.       if ((CurrentMDU % CFrame->ResyncInterval)==0) 
  1419.         {
  1420.           if (!CleartoResync)               /* If not in error recovery*/
  1421.         ReadResync();                          /* read resync. */
  1422.           if (CleartoResync)
  1423.         {
  1424.           /* 
  1425.             Clear until we have LastKnownResync:
  1426.             the offset is by 1 because we add the resync i%8
  1427.             _after_ we code the ith resync interval...
  1428.             */
  1429.           if (((CurrentMDU/CFrame->ResyncInterval)&0x07)==
  1430.               ((LastKnownResync+1)&0x07))
  1431.             CleartoResync = 0;   /* Finished with resync clearing */
  1432.         }
  1433.           UseType=1;                             /* Reset codec */
  1434.           for(j=0;j<CScan->NumberComponents;j++) /* reset line buffers */
  1435.         {                                    /* Type is previous pel */
  1436.           InstallIob(j);
  1437.           LineResetBuffers();
  1438.         }
  1439.         }
  1440.     }
  1441.       if (!(CurrentMDU%CScan->MDUWide)&&(CurrentMDU))  /* Reset CScan type */
  1442.     {
  1443.       UseType=2;                            /* Start of line */
  1444.       StartofLine=1;                        /* uses top pel predictor */
  1445.     }
  1446.  
  1447.       if (CurrentElem>=NumberElem)
  1448.     {
  1449.       NumberElem = MIN((CScan->MDUWide-(CurrentMDU%CScan->MDUWide)),
  1450.                MaxElem);
  1451.       CurrentElem=0;
  1452.       for(j=0;j<CScan->NumberComponents;j++)
  1453.         {
  1454.           InstallIob(j);                    /* Install component j */
  1455.           ReadPreambleLine(NumberElem,     /* Read in some elements*/
  1456.                    CScan->LosslessBuffer[j]); 
  1457.         }
  1458.     }
  1459.       if (CScan->NumberComponents==1)
  1460.     {
  1461.       width=horfreq*NumberElem+1;
  1462.       input = &CScan->LosslessBuffer[0][CurrentElem];
  1463.       switch(UseType) /* Same as lossless coding predictor*/
  1464.         {
  1465.         case 1:
  1466.           px = input[width];
  1467.           break;
  1468.         case 2:
  1469.           px = input[1];
  1470.           break;
  1471.         case 3:
  1472.           px = input[0];
  1473.           break;
  1474.         case 4:
  1475.           px = input[width] + input[1] - input[0];
  1476.           break;
  1477.         case 5:
  1478.           px = input[width] + ((input[1] - input[0])>>1);
  1479.           break;
  1480.         case 6:
  1481.           px = input[1] + ((input[width] - input[0])>>1);
  1482.           break;
  1483.         case 7:
  1484.           px = (input[1] + input[width])>>1;  /* No rounding */
  1485.           break;
  1486.         default:
  1487.           WHEREAMI();
  1488.           printf("Lossless mode %d not supported.\n",UseType);
  1489.           break;
  1490.         }
  1491.       if (CleartoResync)         /* If CleartoResync, flush */
  1492.         input[width+1] = 0;
  1493.       else
  1494.         {
  1495.           value = LosslessDecodeDC();
  1496.           input[width+1] = (value+px)&0xffff;
  1497.           if (Loud > MUTE)
  1498.         {
  1499.           printf("OUT=%d  PX=%d  VAL: %d\n",
  1500.              input[width+1],px,value);
  1501.         }
  1502.         }
  1503.     }
  1504.       else
  1505.     {
  1506.       for(j=0;j<CScan->NumberComponents;j++)   /* Decode MDU */
  1507.         {
  1508.           if (Loud > MUTE)
  1509.         {
  1510.           WHEREAMI();
  1511.           printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n",
  1512.              j,CurrentMDU,NumberMDU);
  1513.         }
  1514.           InstallIob(j);                     /* Install component */
  1515.           height=CFrame->vf[CScan->ci[j]];
  1516.           horfreq=CFrame->hf[CScan->ci[j]];
  1517.           width=horfreq*NumberElem+1;
  1518.           input = &CScan->LosslessBuffer[j][CurrentElem*horfreq];
  1519.           UseDCHuffman(CScan->td[j]);          /* Install DC table */
  1520.           for(v=1;v<=height;v++)
  1521.         {
  1522.           for(h=1;h<=horfreq;h++)
  1523.             {
  1524.               switch(UseType) /* Same as lossless coding predictor*/
  1525.             {
  1526.             case 1:
  1527.               px = input[(v*(width))+h-1];
  1528.               break;
  1529.             case 2:
  1530.               px = input[((v-1)*(width))+h];
  1531.               break;
  1532.             case 3:
  1533.               px = input[((v-1)*(width))+h-1];
  1534.               break;
  1535.             case 4:
  1536.               px = input[(v*(width))+h-1] +
  1537.                 input[((v-1)*(width))+h] -
  1538.                   input[((v-1)*(width))+h-1];
  1539.               break;
  1540.             case 5:
  1541.               px = input[(v*(width))+h-1] +
  1542.                 ((input[((v-1)*(width))+h] -
  1543.                   input[((v-1)*(width))+h-1])>>1);
  1544.               break;
  1545.             case 6:
  1546.               px = input[((v-1)*(width))+h] +
  1547.                 ((input[(v*(width))+h-1] -
  1548.                   input[((v-1)*(width))+h-1])>>1);
  1549.               break;
  1550.             case 7:
  1551.               px = (input[((v-1)*(width))+h] +
  1552.                 input[(v*(width))+h-1])>>1;
  1553.               break;
  1554.             default:
  1555.               WHEREAMI();
  1556.               printf("Lossless mode %d not supported.\n",
  1557.                  UseType);
  1558.               break;
  1559.             }
  1560.               if (CleartoResync)         /* If CleartoResync, flush */
  1561.             input[(v*(width))+h] = 0;
  1562.               else
  1563.             {
  1564.               value = LosslessDecodeDC();
  1565.               input[(v*(width))+h] = (value+px)&0xffff;
  1566.               if (Loud > MUTE)
  1567.                 {
  1568.                   printf("OUT=%d  PX=%d  VAL: %d\n",
  1569.                      input[(v*(width))+h],px,value);
  1570.                 }
  1571.             }
  1572.             }
  1573.         }
  1574.         }
  1575.     }
  1576.       CurrentElem++;
  1577.       if (CurrentElem>=NumberElem)
  1578.     {
  1579.       for(j=0;j<CScan->NumberComponents;j++)
  1580.         {
  1581.           InstallIob(j);                    /* Install component j */
  1582.           WriteLine(NumberElem,             /* Write out elements*/
  1583.             CScan->LosslessBuffer[j]); 
  1584.         }
  1585.     }
  1586.       CurrentMDU++;
  1587.       if (StartofLine)
  1588.     {
  1589.       UseType=CScan->SSS;
  1590.       StartofLine=0;
  1591.     }
  1592.     }
  1593. }
  1594.  
  1595. /*BFUNC
  1596.  
  1597. JpegDecodeScan() is used to decode a portion of the image called the
  1598. scan.  Everything  is read upon getting to this stage.
  1599.  
  1600. EFUNC*/
  1601.  
  1602. static void JpegDecodeScan()
  1603. {
  1604.   BEGIN("JpegDecodeScan");
  1605.   int j,v,h,dovf,dohf;
  1606.   int input[64],output[64];
  1607.   int IDCTBound,IDCTShift;
  1608.  
  1609.   while(1)
  1610.     {
  1611.       if ((NumberMDU<0)&&(!(CurrentMDU%CScan->MDUWide)))
  1612.     {
  1613.       if (CheckMarker()==0xdc)
  1614.         ScreenMarker();
  1615.     }
  1616.       if (NumberMDU>=0)               /* If NumberMDU is positive proceed */
  1617.     {
  1618.       if (CurrentMDU >= NumberMDU) /* If all decoded */
  1619.         return;
  1620.     }
  1621.       if (CFrame->ResyncInterval)                /* Flag to decoder stream */
  1622.     {
  1623.       ResyncEnable = 1;
  1624.     }
  1625.       if (CurrentMDU && (CFrame->ResyncInterval))
  1626.     {                                    /* If resync interval */
  1627.       if ((CurrentMDU % CFrame->ResyncInterval)==0) 
  1628.         {
  1629.           if (!CleartoResync)               /* If not in error recovery*/
  1630.         {                               /* read resync. */
  1631.           ReadResync();
  1632.         }
  1633.           if (CleartoResync)
  1634.         {
  1635.           /* 
  1636.             Clear until we have LastKnownResync:
  1637.             the offset is by 1 because we add the resync i%8
  1638.             _after_ we code the ith resync interval...
  1639.             */
  1640.           if (((CurrentMDU/CFrame->ResyncInterval)&0x07)==
  1641.               ((LastKnownResync+1)&0x07))
  1642.             {
  1643.               CleartoResync = 0;   /* Finished with resync clearing */
  1644.             }
  1645.         }
  1646.             ResetCodec();                /* Reset codec */
  1647.         }
  1648.     }
  1649.       IDCTBound=((CFrame->DataPrecision>8)?4095:255);
  1650.       IDCTShift=((CFrame->DataPrecision>8)?2048:128);
  1651.       for(j=0;j<CScan->NumberComponents;j++)   /* Decode MDU */
  1652.     {
  1653.       if (Loud > MUTE)
  1654.         {
  1655.           WHEREAMI();
  1656.           printf("[Decoder Pass [Component:MDU:#MDU] [%d:%d:%d]]\n",
  1657.              j,CurrentMDU,NumberMDU);
  1658.         }
  1659.       InstallPrediction(j);             /* Install component */
  1660.       InstallIob(j);
  1661.       if (CScan->NumberComponents==1) /* Check for non-interleaved mode */
  1662.         dohf=dovf=1;
  1663.       else
  1664.         {
  1665.           dohf = CFrame->hf[CScan->ci[j]];
  1666.           dovf = CFrame->vf[CScan->ci[j]];
  1667.         }
  1668.       for(v=0;v<dovf;v++) /* Do for blocks in MDU*/
  1669.         {
  1670.           for(h=0;h<dohf;h++)
  1671.         {
  1672.           if (CleartoResync)             /* CleartoResync, flush */
  1673.             ClearMatrix(input);
  1674.           else
  1675.             {
  1676.               UseDCHuffman(CScan->td[j]);  /* Install DC table */
  1677.               *input = DecodeDC();         /* Decode DC */
  1678.               UseACHuffman(CScan->ta[j]);  /* Install AC table */
  1679.               DecodeAC(input);             /* Decode AC */
  1680.               if (Loud > TALK)
  1681.             {
  1682.               printf("Cooked Input\n");
  1683.               PrintMatrix(input);
  1684.             }
  1685.               IZigzagMatrix(input,output);   /* Inverse zigzag */
  1686.               IQuantize(output,              /* Inverse quantize */
  1687.                 CImage->
  1688.                 QuantizationMatrices[CFrame->
  1689.                              tq[CScan->ci[j]]]);
  1690.               DefaultIDct(output,input);     /* Inverse DCT */
  1691.               PostshiftIDctMatrix(input,IDCTShift);
  1692.               /* Shift (all positive)*/
  1693.               BoundIDctMatrix(input,IDCTBound); /* Bound */
  1694.               if (Loud > WHISPER)
  1695.             {
  1696.               printf("Raw Output\n");
  1697.               PrintMatrix(input);
  1698.             }
  1699.             }
  1700.           WriteBlock(input);                 /* Write out */
  1701.         }
  1702.         }
  1703.     }
  1704.       CurrentMDU++;
  1705.     }
  1706. }
  1707.  
  1708. /*BFUNC
  1709.  
  1710. PrintImage() prints out the Image structure of the CURRENT image.  It
  1711. is primarily used for debugging. The image structure consists of the
  1712. data that is held to be fixed even though multiple scans (or multiple
  1713. frames, even though it is not advertised as such by JPEG) are
  1714. received.
  1715.  
  1716. EFUNC*/
  1717.  
  1718. void PrintImage()
  1719. {
  1720.   BEGIN("PrintImage");
  1721.   int i;
  1722.  
  1723.   printf("*** Image ID: %x ***\n",CImage);
  1724.   if (CImage)
  1725.     {
  1726.       if (CImage->StreamFileName)
  1727.     {
  1728.       printf("StreamFileName %s\n",(CImage->StreamFileName ?
  1729.                     CImage->StreamFileName :
  1730.                     "Null"));
  1731.     }
  1732.       printf("InternalMode: %d   ImageSequence: %d\n",
  1733.          CImage->JpegMode,CImage->ImageSequence);
  1734.       printf("NumberQuantizationMatrices %d\n",
  1735.          CImage->NumberQuantizationMatrices);
  1736.       for(i=0;i<CImage->NumberQuantizationMatrices;i++)
  1737.     {
  1738.       printf("Quantization Matrix [%d]\n",i);
  1739.       PrintMatrix(CImage->QuantizationMatrices[i]);
  1740.     }
  1741.       printf("NumberDCTables %d\n",
  1742.          CImage->NumberDCTables);
  1743.       for(i=0;i<CImage->NumberDCTables;i++)
  1744.     {
  1745.       printf("DC Huffman Table[%d]\n",i);
  1746.       UseDCHuffman(i);
  1747.       PrintHuffman();
  1748.     }
  1749.       printf("NumberACTables %d\n",
  1750.          CImage->NumberACTables);
  1751.       for(i=0;i<CImage->NumberACTables;i++)
  1752.     {
  1753.       printf("AC Huffman Table[%d]\n",i);
  1754.       UseACHuffman(i);
  1755.       PrintHuffman();
  1756.     }
  1757.     }
  1758. }
  1759.  
  1760. /*BFUNC
  1761.  
  1762. PrintFrame() is used to print the information specific to loading in
  1763. the frame. This corresponds roughly to the information received by the
  1764. SOF marker code.
  1765.  
  1766. EFUNC*/
  1767.  
  1768. void PrintFrame()
  1769. {
  1770.   BEGIN("PrintFrame");
  1771.   int i;
  1772.  
  1773.   printf("*** Frame ID: %x *** (TYPE: %d)\n",CFrame,CFrame->Type);
  1774.   if (CFrame)
  1775.     {
  1776.       printf("DataPrecision: %d  ResyncInterval: %d\n",
  1777.          CFrame->DataPrecision,CFrame->ResyncInterval);
  1778.       printf("Height: %d   Width: %d\n",
  1779.          CFrame->GlobalHeight,CFrame->GlobalWidth);
  1780.       printf("BufferSize: %d  Image: %x\n",CFrame->BufferSize,CFrame->Image);
  1781.       printf("NumberComponents %d\n",
  1782.          CFrame->GlobalNumberComponents);
  1783.       for(i=0;i<CFrame->GlobalNumberComponents;i++)
  1784.     {
  1785.       printf("ComponentFileName %s\n",
  1786.          ((CFrame->ComponentFileName[CFrame->cn[i]]) ?
  1787.           CFrame->ComponentFileName[CFrame->cn[i]] : "Null"));
  1788.       printf("HorizontalFrequency: %d  VerticalFrequency: %d\n",
  1789.          CFrame->hf[CFrame->cn[i]],CFrame->vf[CFrame->cn[i]]);
  1790.       printf("Height: %d  Width: %d\n",
  1791.          CFrame->Height[CFrame->cn[i]],CFrame->Width[CFrame->cn[i]]);
  1792.       InstallIob(i);
  1793.       PrintIob();
  1794.     }
  1795.     }
  1796. }
  1797.  
  1798. /*BFUNC
  1799.  
  1800. PrintScan() is used to print the information in the CScan structure.
  1801. This roughly corresponds to the information received by the Scan
  1802. marker code.
  1803.  
  1804. EFUNC*/
  1805.  
  1806. void PrintScan()
  1807. {
  1808.   BEGIN("PrintScan");
  1809.   int i;
  1810.  
  1811.   printf("*** Scan ID: %x ***\n",CScan);
  1812.   if (CScan)
  1813.     {
  1814.       printf("NumberComponents %d\n",
  1815.          CScan->NumberComponents);
  1816.       for(i=0;i<CScan->NumberComponents;i++)
  1817.     {
  1818.       printf("Component: %d  Index: %d\n",
  1819.          i,CScan->ci[i]);
  1820.       printf("DC Huffman Table: %d  AC Huffman Table: %d\n",
  1821.          CScan->td[i],CScan->ta[i]);
  1822.       printf("LastDC: %d  Iob: %x\n",
  1823.          *(CScan->LastDC[i]),CScan->Iob[i]);
  1824.     }
  1825.       printf("NumberACSend: %d  NumberDCSend: %d  NumberQSend: %d\n",
  1826.          CScan->NumberACTablesSend,
  1827.          CScan->NumberDCTablesSend,
  1828.          CScan->NumberQTablesSend);
  1829.     }
  1830. }
  1831.  
  1832. /*BFUNC
  1833.  
  1834. MakeImage() makes an image and puts it into the Current Image pointer
  1835. (CImage). It initializes the structure appropriate to the JPEG initial
  1836. specifications.
  1837.  
  1838. EFUNC*/
  1839.  
  1840. void MakeImage()
  1841. {
  1842.   BEGIN("MakeImage");
  1843.  
  1844.   if (!(CImage = MakeStructure(IMAGE)))
  1845.     {
  1846.       WHEREAMI();
  1847.       printf("Cannot allocate memory for Image structure.\n");
  1848.       exit(ERROR_MEMORY);
  1849.     }
  1850.   CImage->StreamFileName = NULL;
  1851.   CImage->JpegMode = 0;
  1852.   CImage->Jfif=0;
  1853.   CImage->ImageSequence = -1;        /* First element in sequence is 0 */
  1854.   CImage->NumberQuantizationMatrices = 2;  /* Default # matrices is 2 */
  1855.   CImage->QuantizationMatrices[0] = LuminanceQuantization;
  1856.   CImage->QuantizationMatrices[1] = ChrominanceQuantization;
  1857.   CImage->NumberACTables = 0;       /* No tables defined yet */
  1858.   CImage->NumberDCTables = 0;
  1859. }
  1860.  
  1861. /*BFUNC
  1862.  
  1863. MakeFrame() constructs a Frame Structure and puts it in the Current
  1864. Frame pointer (CFrame).
  1865.  
  1866. EFUNC*/
  1867.  
  1868. void MakeFrame()
  1869. {
  1870.   BEGIN("MakeFrame");
  1871.   int i;
  1872.  
  1873.   if (!(CFrame = MakeStructure(FRAME)))
  1874.     {
  1875.       WHEREAMI();
  1876.       printf("Cannot allocate memory for Frame structure.\n");
  1877.       exit(ERROR_MEMORY);
  1878.     }
  1879.   CFrame->Type=0;                   /* Baseline type */
  1880.   CFrame->InsertDnl = 0;            /* Set to default position */
  1881.   CFrame->Q = 0;
  1882.   CFrame->GlobalHeight = 0;
  1883.   CFrame->GlobalWidth = 0;
  1884.   CFrame->DataPrecision = 8;         /* Default 8 precision */
  1885.   CFrame->ResyncInterval = 0;
  1886.   CFrame->GlobalNumberComponents = 0;
  1887.   for(i=0;i<MAXIMUM_COMPONENTS;i++)
  1888.     {
  1889.       CFrame->cn[i] = 0;           /* Clean out all slots */
  1890.       CFrame->hf[i] = 0; 
  1891.       CFrame->vf[i] = 0;
  1892.       CFrame->tq[i] = 0;
  1893.       CFrame->Height[i] = 0;
  1894.       CFrame->Width[i] = 0;
  1895.     }
  1896.   CFrame->BufferSize = BUFFERSIZE;
  1897.   CFrame->Image = CImage;
  1898. }
  1899.  
  1900. /*BFUNC
  1901.  
  1902. MakeScanFrequency() constructs a set of scan information for the
  1903. current variables. These frequency markers are used for creating the
  1904. JPEG custom matrices.
  1905.  
  1906. EFUNC*/
  1907.  
  1908. void MakeScanFrequency()
  1909. {
  1910.   BEGIN("MakeScanFrequency");
  1911.   int i;
  1912.  
  1913.   for(i=0;i<MAXIMUM_SOURCES;i++)
  1914.     {
  1915.       if (!(CScan->LastDC[i] = MakeStructure(int)))
  1916.     {
  1917.       WHEREAMI();
  1918.       printf("Cannot allocate LastDC integer store.\n");
  1919.       exit(ERROR_MEMORY);
  1920.     }
  1921.       if (!(CScan->ACFrequency[i] = (int *) calloc(257,sizeof(int))))
  1922.     {
  1923.       WHEREAMI();
  1924.       printf("Cannot allocate AC Frequency array.\n");
  1925.       exit(ERROR_MEMORY);
  1926.     }
  1927.       if (!(CScan->DCFrequency[i] = (int *) calloc(257,sizeof(int))))
  1928.     {
  1929.       WHEREAMI();
  1930.       printf("Cannot allocate DC Frequency array.\n");
  1931.       exit(ERROR_MEMORY);
  1932.     }
  1933.     }
  1934. }
  1935.  
  1936. /*BFUNC
  1937.  
  1938. MakeScan() is used for creating the Scan structure which holds most of
  1939. the information in the Scan marker code.
  1940.  
  1941. EFUNC*/
  1942.  
  1943. void MakeScan()
  1944. {
  1945.   BEGIN("MakeScan");
  1946.   int i;
  1947.  
  1948.   if (!(CScan = MakeStructure(SCAN)))
  1949.     {
  1950.       WHEREAMI();
  1951.       printf("Cannot allocate memory for Scan structure.\n");
  1952.       exit(ERROR_MEMORY);
  1953.     }
  1954.   CScan->NumberACTablesSend = 0;    /* Install with default values */
  1955.   CScan->NumberDCTablesSend = 0;
  1956.   CScan->NumberComponents = 0;
  1957.   for(i=0;i<MAXIMUM_SOURCES;i++)
  1958.     {
  1959.       CScan->ta[i] = 0;
  1960.       CScan->td[i] = 0;
  1961.       CScan->sa[i] = 0;
  1962.       CScan->sd[i] = 0;
  1963.       CScan->sq[i] = 0;
  1964.     }
  1965.   CScan->SSS=0;
  1966.   CScan->SSE=0;
  1967.   CScan->SAH=0;
  1968.   CScan->SAL=0;
  1969.   MakeScanFrequency();
  1970. }
  1971.  
  1972. /*BFUNC
  1973.  
  1974. MakeConsistentFileNames() is used to construct consistent filenames
  1975. for opening and closing of data storage. It is used primarily by the
  1976. decoder when all the files may not necessarily be specified.
  1977.  
  1978. EFUNC*/
  1979.  
  1980. void MakeConsistentFileNames()
  1981. {
  1982.   BEGIN("MakeConsistentFileNames");
  1983.   int i;
  1984.  
  1985.   for(i=0;i<CScan->NumberComponents;i++)
  1986.     {
  1987.       if (CImage->ImageSequence)  /* If in sequence, must add sequence */
  1988.     {                         /* identifier */
  1989.       CFrame->ComponentFileName[CScan->ci[i]] = 
  1990.         (char *) calloc(strlen(CImage->StreamFileName)+16,sizeof(char));
  1991.       sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d.%d",
  1992.           CImage->StreamFileName,CImage->ImageSequence,CScan->ci[i]);
  1993.     }
  1994.       else if (CFrame->ComponentFileName[CScan->ci[i]] == NULL)
  1995.     {                        /* Otherwise if none specified, create. */
  1996.       CFrame->ComponentFileName[CScan->ci[i]] = 
  1997.         (char *) calloc(strlen(CImage->StreamFileName)+8,sizeof(char));
  1998.       sprintf(CFrame->ComponentFileName[CScan->ci[i]],"%s.%d",
  1999.           CImage->StreamFileName,CScan->ci[i]);
  2000.     }
  2001.     }
  2002. }
  2003.  
  2004. /*BFUNC
  2005.  
  2006. CheckValidity() checks whether the current values in CFrame and CScan
  2007. meet the internal specifications for correctness and the algorithm
  2008. can guarantee completion.
  2009.  
  2010. EFUNC*/
  2011.  
  2012. void CheckValidity()
  2013. {
  2014.   BEGIN("CheckValidity");
  2015.   int i;
  2016.  
  2017.   ErrorValue = 0;           /* Check if within internal specs */
  2018.   InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width");
  2019.   InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height");
  2020.   if (CFrame->Q<0)
  2021.     {
  2022.       WHEREAMI();
  2023.       printf("Q factor is negative - must be positive\n");
  2024.     }
  2025.   if ((CFrame->DataPrecision!=8)&&(CFrame->DataPrecision!=12))
  2026.     {
  2027.       if (CImage->JpegMode == J_LOSSLESS)
  2028.     {
  2029.       if (CFrame->DataPrecision<=16)
  2030.         printf("Precision type: %d\n",CFrame->DataPrecision);
  2031.       else
  2032.         printf("Caution: precision type: %d greater than 16.\n",
  2033.            CFrame->DataPrecision);
  2034.     }
  2035.       else
  2036.     printf("Caution: precision type: %d not 8 or 12.\n",
  2037.            CFrame->DataPrecision);
  2038.     }
  2039.   InBounds(CScan->NumberComponents,1,15,"Bad Number of Components");
  2040.   for(i=0;i<CScan->NumberComponents;i++)
  2041.     {
  2042.       InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH,
  2043.            "Bad Frame Width");
  2044.       InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT,
  2045.            "Bad Frame Height");
  2046.       InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_HORIZONTAL_FREQUENCY,
  2047.            "Bad Horizontal Frequency");
  2048.       InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_VERTICAL_FREQUENCY,
  2049.            "Bad Vertical Frequency");
  2050.     }
  2051.   InBounds(LosslessPredictorType,0,7,"Bad Lossless Predictor Type");
  2052.   if (PointTransform)
  2053.     {
  2054.       if (!(LosslessPredictorType))
  2055.     {
  2056.       WHEREAMI();
  2057.       printf("Point Transform specified without lossless prediction.\n");
  2058.       printf("Shifting of input/output should be anticipated.\n");
  2059.     }
  2060.       else
  2061.     InBounds(PointTransform,0,14,"Bad Point Transform");
  2062.     }
  2063.   if (ErrorValue)
  2064.     {
  2065.       WHEREAMI();
  2066.       printf("Invalid input detected.\n");
  2067.       exit(ErrorValue);
  2068.     }
  2069. }
  2070.  
  2071. /*BFUNC
  2072.  
  2073. CheckBaseline() checks whether the internal values meet JPEG Baseline
  2074. specifications.
  2075.  
  2076. EFUNC*/
  2077.  
  2078. int CheckBaseline()
  2079. {
  2080.   BEGIN("CheckBaseline");
  2081.   int i;
  2082.  
  2083.   ErrorValue = 0;         /* Check for JPEG specs */
  2084.   InBounds(CFrame->GlobalWidth,0,MAXIMUM_IMAGE_WIDTH,"Bad Image Width");
  2085.   InBounds(CFrame->GlobalHeight,0,MAXIMUM_IMAGE_HEIGHT,"Bad Image Height");
  2086.   if (CFrame->Q<0)
  2087.     {
  2088.       WHEREAMI();
  2089.       printf("Q factor is negative - must be positive\n");
  2090.     }
  2091.   InBounds(CScan->NumberComponents,1,4,"Bad Number of Components");
  2092.   for(i=0;i<CScan->NumberComponents;i++)
  2093.     {
  2094.       InBounds(CFrame->Width[CScan->ci[i]],0,MAXIMUM_IMAGE_WIDTH,
  2095.            "Bad Frame Width");
  2096.       InBounds(CFrame->Height[CScan->ci[i]],0,MAXIMUM_IMAGE_HEIGHT,
  2097.            "Bad Frame Height");
  2098.       InBounds(CFrame->hf[CScan->ci[i]],1,MAXIMUM_JPEG_HORIZONTAL_FREQUENCY,
  2099.            "Bad Horizontal Frequency");
  2100.       InBounds(CFrame->vf[CScan->ci[i]],1,MAXIMUM_JPEG_VERTICAL_FREQUENCY,
  2101.            "Bad Vertical Frequency");
  2102.     }
  2103.   if (ErrorValue)
  2104.     {
  2105.       printf("Caution: JPEG++ Mode.\n");
  2106.       ErrorValue = 0;
  2107.     }
  2108. }
  2109.  
  2110. /*BFUNC
  2111.  
  2112. ConfirmFileSize() checks to see if the files used in the scan actually
  2113. exist and correspond in size to the input given.
  2114.  
  2115. EFUNC*/
  2116.  
  2117. void ConfirmFileSize()
  2118. {
  2119.   BEGIN("ConfirmFileSize");
  2120.   int i,FileSize;
  2121.   FILE *test;
  2122.  
  2123.   for(i=0;i<CScan->NumberComponents;i++)  /* Do for all components in scan*/
  2124.     {
  2125.       if (CFrame->ComponentFileName[CScan->ci[i]])
  2126.     {
  2127.       if ((test = fopen(CFrame->ComponentFileName[CScan->ci[i]],
  2128.                 "r")) == NULL)
  2129.         {
  2130.           WHEREAMI();
  2131.           printf("Cannot open filename %s\n",
  2132.              CFrame->ComponentFileName[CScan->ci[i]]);
  2133.           exit(ERROR_BOUNDS);
  2134.         }
  2135.       fseek(test,0,2);                /* Go to end */
  2136.       FileSize = ftell(test);         /* Find number of bytes */
  2137.       rewind(test);
  2138.       if (CFrame->Height[CScan->ci[i]] == 0)  /* Must have good dimens*/
  2139.         {
  2140.           if (CFrame->Width[CScan->ci[i]] == 0)
  2141.         {
  2142.           WHEREAMI();
  2143.           printf("Bad file specification in %s.\n",
  2144.              CFrame->ComponentFileName[CScan->ci[i]]);
  2145.         }
  2146.           else
  2147.         {
  2148.           CFrame->Height[CScan->ci[i]] = FileSize /
  2149.             (CFrame->Width[CScan->ci[i]]*
  2150.               ((CFrame->DataPrecision>8)?2:1));
  2151.           WHEREAMI();
  2152.           printf("Autosizing height to %d\n",
  2153.              CFrame->Height[CScan->ci[i]]);
  2154.         }
  2155.         }                                 /* Dimensions must conform */
  2156.       if (FileSize !=
  2157.           CFrame->Width[CScan->ci[i]] * CFrame->Height[CScan->ci[i]]*
  2158.           ((CFrame->DataPrecision>8)?2:1)) 
  2159.         {
  2160.           WHEREAMI();
  2161.           printf("File size conflict in %s, est: %d  act: %d \n",
  2162.              CFrame->ComponentFileName[CScan->ci[i]],
  2163.              CFrame->Width[CScan->ci[i]]*CFrame->Height[CScan->ci[i]]*
  2164.              ((CFrame->DataPrecision>8)?2:1),
  2165.              FileSize);
  2166.           exit(ERROR_BOUNDS);
  2167.         }
  2168.       fclose(test);
  2169.     }
  2170.     }
  2171. }
  2172.  
  2173. /*BFUNC
  2174.  
  2175. Help() prints out general information regarding the use of this
  2176. JPEG software.
  2177.  
  2178. EFUNC*/
  2179.  
  2180. static void Help()
  2181. {
  2182.   BEGIN("Help");
  2183.  
  2184.   printf("jpeg -iw ImageWidth -ih ImageHeight [-JFIF] [-q(l) Q-Factor]\n");
  2185.   printf("     [-a] [-b] [-d] [-k predictortype] [-n] [-o] [-y] [-z]\n");
  2186.   printf("     [-p PrecisionValue] [-t pointtransform]\n");
  2187.   printf("     [-r ResyncInterval] [-s StreamName]\n");
  2188.   printf("     [[-ci ComponentIndex1] [-fw FrameWidth1] [-fh FrameHeight1]\n");
  2189.   printf("      [-hf HorizontalFrequency1] [-vf VerticalFrequency1]\n");
  2190.   printf("      ComponentFile1]\n");
  2191.   printf("     [[-ci ComponentIndex2] [-fw FrameWidth2] [-fh FrameHeight2]\n");
  2192.   printf("      [-hf HorizontalFrequency2] [-vf VerticalFrequency2]\n");
  2193.   printf("      ComponentFile1]\n");
  2194.   printf("     ....\n\n");
  2195.   printf("-JFIF puts a JFIF marker. Don't change component indices.\n");
  2196.   printf("-a enables Reference DCT.\n");
  2197.   printf("-b enables Lee DCT.\n");
  2198.   printf("-d decoder enable.\n");
  2199.   printf("-[k predictortype] enables lossless mode.\n");
  2200.   printf("-q specifies quantization factor; -ql specifies can be long.\n");
  2201.   printf("-n enables non-interleaved mode.\n");
  2202.   printf("-[t pointtransform] is the number of bits for the PT shift.\n");
  2203.   printf("-o enables the Command Interpreter.\n");
  2204.   printf("-p specifies precision.\n");
  2205.   printf("-y run in robust mode against errors (cannot be used with DNL).\n");
  2206.   printf("-z uses default Huffman tables.\n");
  2207. }
  2208.  
  2209. /*END*/
  2210.